package com.sj.proxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Proxy1 {

    //用来产生新的代理类
    public static Object newProxyInstance(Class interface_) throws Exception {
        String rt = "\r\n";
        String methodStr = "";

        Method[] methods = interface_.getMethods();
        for (Method m : methods) {
            methodStr += "    public void " + m.getName() + "() {" + rt +
                    "        long start = System.currentTimeMillis();" + rt +
                    "        System.out.println(\"starttime: \" + start);" + rt +
                    "        t.move();" + rt +
                    "        long end = System.currentTimeMillis();" + rt +
                    "        System.out.println(\"time: \" + (end - start));" + rt +
                    "    }" + rt;
        }

        String src = "package com.sj.proxy;" + rt +
                "public class TankTimeProxy implements " + interface_.getName() + " {" + rt +
                "    private IMoveable t;" + rt +

                "    public TankTimeProxy(IMoveable t) {" + rt +
                "        super();" + rt +
                "        this.t = t;" + rt +
                "    }" + rt +
                methodStr +
                "}";

        //先把源代码写到下面
        String fileName = "D:/SpringLearn/DynamicProxy/src/TankTimeProxy.java";
        File f = new File(fileName);
        FileWriter fw = new FileWriter(f);
        fw.write(src);
        fw.flush();
        fw.close();

        //在程序中编译这段代码
        //JavaCompiler java的编译器
        //ToolProvider.getSystemJavaCompiler() 拿到系统当前默认的java编译器，其实就是javac
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        //通过fileMgr管理要编译的文件
        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
        //拿到编译的内容
        Iterable<? extends JavaFileObject> units = fileMgr.getJavaFileObjects(fileName);
        //编译的任务
        JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
        t.call();//编译
        fileMgr.close();

        //生成了这个TankTimeProxy.class之后，将其load到内存，并且生成一个对象
        URL[] urls = new URL[]{new URL("file:/"+"d:/src/")};
        URLClassLoader urlClassLoader = new URLClassLoader(urls);
        Class class_ = urlClassLoader.loadClass("com.sj.proxy.TankTimeProxy");
        //站在java虚拟机的角度，每一个类、每一个类里面的每一个方法都是一个对象
        Constructor constructor = class_.getConstructor(interface_);
        Object object = constructor.newInstance(new Tank());

        return object;
    }
}
